package game.controller;

import com.google.common.collect.Lists;
import common.config.exception.CustomException;
import common.controller.base.BaseController;
import common.model.enums.ProductiveEnum;
import common.model.po.GBuilding;
import common.model.po.GItem;
import common.model.po.GRecipe;
import common.model.request.base.PaginationRequest;
import common.model.response.base.Result;
import common.util.BigFractionUtil;
import game.model.request.SaveRecipeRequest;
import game.model.request.SearchRecipeRequest;
import game.service.GBuildingService;
import game.service.GItemService;
import game.service.GRecipeService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.math3.fraction.BigFraction;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 配方和原料的多对多关系前端控制器
 *
 * @author 米泽鹏
 * @since 2022-02-26
 */
@Api(tags = "配方管理")
@RestController
@RequestMapping("/game/g-recipe")
public class GRecipeController extends BaseController {

	@Resource
	private GRecipeService recipeService;
	@Resource
	private GItemService itemService;
	@Resource
	private GBuildingService buildingService;

	@ApiOperation(value = "配方分页查询", notes = "配方分页查询")
	@PostMapping("/readOnly/pageRecipe")
	public Result<?> pageRecipe(@ApiParam(value = "配方分页查询请求", required = true) @RequestBody PaginationRequest<SearchRecipeRequest, GRecipe> paginationRequest) {
		SearchRecipeRequest request = paginationRequest.getParams();
		if (request.getProductItemId() != null && request.getProductBuildingId() != null) {
			throw new CustomException("在产物中，物品和建筑只能选择一个");
		}
		return successWithData(recipeService.pageRecipe(paginationRequest));
	}

	@ApiOperation(value = "获取所有物品", notes = "获取所有物品")
	@PostMapping("/readOnly/getAllItem")
	public Result<?> getAllItem() {
		return successWithData(itemService.lambdaQuery().select(GItem::getId, GItem::getItemName, GItem::getImage, GItem::getFluid).list());
	}

	@ApiOperation(value = "获取所有建筑", notes = "获取所有建筑")
	@PostMapping("/readOnly/getAllBuilding")
	public Result<?> getAllBuilding() {
		List<GBuilding> buildingList = buildingService.lambdaQuery().orderByAsc(GBuilding::getCustomSort).select(GBuilding::getId, GBuilding::getBuildingName, GBuilding::getImage, GBuilding::getPower, GBuilding::getOverclockable).list();
		return successWithData(buildingList);
	}

	@ApiOperation(value = "获取所有生产建筑", notes = "获取所有生产建筑")
	@PostMapping("/readOnly/getAllProductionBuilding")
	public Result<?> getAllProductionBuilding() {
		List<GBuilding> buildingList = buildingService.lambdaQuery().eq(GBuilding::getProductive, ProductiveEnum.PRODUCTIVE.getValue()).orderByAsc(GBuilding::getCustomSort).select(GBuilding::getId, GBuilding::getBuildingName, GBuilding::getImage, GBuilding::getNeedPower, GBuilding::getPower, GBuilding::getOverclockable).list();
		return successWithData(buildingList);
	}

	@ApiOperation(value = "配方新增或更新（物品）", notes = "配方新增或更新（物品）")
	@PostMapping("/saveRecipeForItem")
	public Result<?> saveRecipeForItem(@ApiParam(value = "配方新增或更新（物品）请求", required = true) @RequestBody @Validated(value = {SaveRecipeRequest.ValidateForItem.class}) SaveRecipeRequest request) {
		// 数据校验1：至少选择一种产物填写分钟数量
		// 数据校验2：如果有多个产物填写了分钟数量，校验比例是否一致
		List<SaveRecipeRequest.Product> productList = request.getProductList().stream().filter(item -> item.getQuantityPerMinute() != null).collect(Collectors.toList());
		if (productList.isEmpty()) {
			throw new CustomException("请至少选择一种产物填写数量（/min）");
		} else if (productList.size() > 1) {
			List<BigFraction> fractionList = Lists.newArrayList();
			for (SaveRecipeRequest.Product product : productList) {
				fractionList.add(BigFractionUtil.valueOf(product.getQuantityPerProduction(), product.getQuantityPerMinute()));
			}
			if (!BigFractionUtil.isAllEquals(fractionList)) {
				throw new CustomException("产物的数量（/min）填写有误");
			}
		}
		return recipeService.saveRecipe(request);
	}

	@ApiOperation(value = "配方新增或更新（建筑）", notes = "配方新增或更新（建筑）")
	@PostMapping("/saveRecipeForBuilding")
	public Result<?> saveRecipeForBuilding(@ApiParam(value = "配方新增或更新（建筑）请求", required = true) @RequestBody @Validated(value = {SaveRecipeRequest.ValidateForBuilding.class}) SaveRecipeRequest request) {
		return recipeService.saveRecipe(request);
	}

	@ApiOperation(value = "配方删除", notes = "配方删除")
	@DeleteMapping("/deleteRecipe/{id}")
	public Result<?> deleteRecipe(@ApiParam(value = "配方id", required = true) @PathVariable Long id) {
		return recipeService.deleteRecipe(id);
	}

}
